package my.admin;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import io.vertx.core.shareddata.LocalMap;
import io.vertx.core.shareddata.SharedData;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.StaticHandler;
import io.vertx.ext.web.sstore.LocalSessionStore;
import io.vertx.ext.web.sstore.SessionStore;
import my.Starter;
import my.common.util.file.FileUtils;

public class AdminRestVerticle extends AbstractVerticle {
	Logger logger = LoggerFactory.getLogger(AdminRestVerticle.class);

	@Override
	public void start(Future<Void> fut) {
		// create a router
		Router router = Router.router(vertx);
		// Bind "/" to our hello message.
		router.route("/").handler(routingContext -> {
			HttpServerResponse response = routingContext.response();
			//鎷︽埅鍣�
			response.putHeader("Access-Control-Allow-Origin","*");
			routingContext.next();
		});
		// read requestBody
		router.route("/admin*").handler(BodyHandler.create());
		//login
		router.route("/admin/login").handler(routingContext->{
			HttpServerRequest request=routingContext.request();
			HttpServerResponse response = routingContext.response();
			String email=request.getParam("email");
			String password=request.getParam("password");
			if(email.equals("admin")&&password.equals("123456")) {
				//local session
				//SessionStore store = LocalSessionStore.create(vertx);
				routingContext.reroute("/static/starter.html");
			}else {
				response.end();
			}
		});
		// get all
		router.get("/admin/verticles").handler(routingContext -> {
			HttpServerRequest request = routingContext.request();
			HttpServerResponse response = routingContext.response();
			SharedData sharedData = vertx.sharedData();
			LocalMap<String, String> verticleNameIdMap = sharedData.getLocalMap("verticleNameIdMap");
			response.end(verticleNameIdMap.toString());

		});
		// get all
		router.get("/admin/verticleIds").handler(routingContext -> {
			HttpServerRequest request = routingContext.request();
			HttpServerResponse response = routingContext.response();
			response.end(vertx.deploymentIDs().toString());

		});
		// get one by id
		router.get("/admin/verticle/:name").handler(routingContext -> {
			HttpServerRequest request = routingContext.request();
			HttpServerResponse response = routingContext.response();
			String name = request.getParam("name");
			SharedData sharedData = vertx.sharedData();
			LocalMap<String, String> verticleNameIdMap = sharedData.getLocalMap("verticleNameIdMap");
			if (verticleNameIdMap.containsKey(name)) {
				response.end(verticleNameIdMap.get(name));
			} else {
				response.setStatusCode(404).end();
				;
			}
		});
		// undeploy
		router.post("/admin/verticle/undeploy").handler(routingContext -> {
			// print requestBody
			// System.out.println(routingContext.getBodyAsString());
			HttpServerRequest request = routingContext.request();
			HttpServerResponse response = routingContext.response();
			String id = request.getParam("id");
			vertx.undeploy(id, res -> {
				if (res.failed()) {
					logger.error("updeploy failed:{}", id);// 涓嶅仛澶勭悊
					response.setStatusCode(500).end(res.cause().getMessage());
				} else {
					SharedData sharedData = vertx.sharedData();
					LocalMap<String, String> verticleNameIdMap = sharedData.getLocalMap("verticleNameIdMap");
					LocalMap<String, String> verticleIdNameMap = sharedData.getLocalMap("verticleIdNameMap");
					String name = verticleIdNameMap.get(id);
					verticleNameIdMap.remove(name);
					verticleIdNameMap.remove(id);
					response.end();
				}
			});

		});
		// deploy
		router.post("/admin/verticle/deploy").handler(routingContext -> {
			// print requestBody
			System.out.println("deploy");
			HttpServerRequest request = routingContext.request();
			HttpServerResponse response = routingContext.response();
			String url = request.getParam("url");
			String name = request.getParam("name");
			System.out.println(url);
			System.out.println(name);
			//校验url
			int index=url.indexOf("::");
			String jarUrl=url.substring(0, index);
			boolean remoteFileExits=FileUtils.checkReomoteFileExits(jarUrl);
			if(remoteFileExits)	{
				vertx.deployVerticle(url, res -> {
					if (res.succeeded()) {
						System.out.println("deploy success");
						SharedData sharedData = vertx.sharedData();
						LocalMap<String, String> verticleNameIdMap = sharedData.getLocalMap("verticleNameIdMap");
						LocalMap<String, String> verticleIdNameMap = sharedData.getLocalMap("verticleIdNameMap");
						verticleNameIdMap.put(name, res.result());
						verticleIdNameMap.put(res.result(), name);
						response.end(res.result());
					} else {
						System.out.println("deploy error");
						response.end(res.cause().getMessage());
					}
					
				});
			}else {
				response.end("url 404");
			}
			
			
			

		});
		boolean isHostConnectable=isHostConnectable("localhost",8070);
		System.out.println("isHostConnectable:"+isHostConnectable);
		//if not bind start httpserver
		if(!isHostConnectable) {
			// Create the HTTP server and pass the "accept" method to the request handler.
			vertx.createHttpServer().requestHandler(router::accept).listen(
					// Retrieve the port from the configuration,
					
					config().getInteger("http.port", 8070), result -> {
						if (result.succeeded()) {
							fut.complete();
						} else {
							System.out.println(result.cause().getMessage());
							fut.fail(result.cause());
						}
					});
		}else {
			System.out.println("address bind error");
			fut.fail("address bind error");
		}
		
	}
	
	 public static boolean isHostConnectable(String host, int port) {
	        Socket socket = new Socket();
	        try {
	            socket.connect(new InetSocketAddress(host, port));
	        } catch (IOException e) {
	            //e.printStackTrace();
	            return false;
	        } finally {
	            try {
	                socket.close();
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
	        return true;
	    }

}
